# --------- 文件信息 ---------- #
# HashFlow.py
# 作者：赵宗义，xinshengzzy@foxmail.com, 2021.01.25
# -------------------- #
from simulators.BaseSimulator import BaseSimulator
from simulators.Buckets import NFBucket
from 标准库 import 累积序列
import mytools
from 文件工具 import 备份数据结构


class NetFlow(BaseSimulator):
    def __init__(self, 内存=1.0):
        super(NetFlow, self).__init__()
        self.表长1 = int(内存*1024.0*1024.0/(19*4.0))
        self.表长2 = self.表长1
        self.表长3 = self.表长1
        self.表长4 = self.表长1
        self.哈希表 = []
        self.设置超时模式()
        for i in range(self.表长1 + self.表长2 + self.表长3 + self.表长4):
            self.哈希表.append(NFBucket())

    def 打印容量(self):
        print("表长1:%d, 表长2:%d, 表长3:%d, 表长4:%d" % (self.表长1, self.表长2, self.表长3, self.表长4))

    def 计算导出周期(self, 带宽消耗):
        pass

    def 周期式数据包处理(self, 标识符, 时间戳):
        pass

    def 计算索引(self, 标识符):
        偏移量 = 累积序列([0, self.表长1, self.表长2, self.表长3])
        索引1 = mytools.hash1(标识符.encode('utf-8')) % self.表长1 + 偏移量[0]
        索引2 = mytools.hash2(标识符.encode('utf-8')) % self.表长2 + 偏移量[1]
        索引3 = mytools.hash3(标识符.encode('utf-8')) % self.表长3 + 偏移量[2]
        索引4 = mytools.hash4(标识符.encode('utf-8')) % self.表长4 + 偏移量[3]
        return [索引1, 索引2, 索引3, 索引4]

    def 超时式数据包处理(self, 标识符, 时间戳):
        索引列表 = self.计算索引(标识符)
        for 索引 in 索引列表:
            if self.哈希表[索引].empty():
                self.哈希表[索引].init(标识符, 1, 时间戳)
                return
            elif self.哈希表[索引].match(标识符):
                self.哈希表[索引].increCnt(1, 时间戳)
                return
            elif self.超时时间 > 0 and self.哈希表[索引].getTs() + self.超时时间 < 时间戳:
                self.导出流记录(self.哈希表[索引].getRecord())
                self.哈希表[索引].init(标识符, 1, 时间戳)
                return

    def 在线流长查询(self, 标识符):
        流长 = 0
        索引列表 = self.计算索引(标识符)
        for idx in 索引列表:
            if self.哈希表[idx].match(flowID):
                流长 += self.哈希表[idx].count
        return 流长

    def 下载数据平面(self):
        流集 = dict()
        for item in self.哈希表:
            if not item.empty():
                标识符, 计数值 = item.getRecord()
                if 标识符 not in 流集:
                    流集[标识符] = 计数值
                else:
                    流集[标识符] += 计数值
        return 流集

    def 重置数据平面(self):
        for 索引 in range(self.表长1 + self.表长2 + self.表长3 + self.表长4):
            self.哈希表[索引].reset()

    def 备份(self, 文件名):
        备份 = dict()
        备份["流记录集"] = self.获取流记录集()
        备份["导出次数"] = self.获取导出次数()
        备份数据结构(备份, 文件名)
